﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Clipper.Model;

namespace Communication
{
    public class Arm        // 臂类(也可称芯片类，直接控制电机的芯片，一个芯片控制4个电机)
    {
        private string mArmName;                // 臂的名称
        private string mCanID;                  // 臂所在芯片编号
        private ControlStatusEnum mStatus;      //状态
        AutoResetEvent mCompleteReset = new AutoResetEvent(false);
        private Motor[] mMotors;                // 电机
        

        
        #region // -------属性---------------
        /// <summary>
        /// 臂的名称
        /// </summary>
        public string ArmName
        {
            get { return mArmName; }
            set { mArmName = value; }
        }

        /// <summary>
        /// 臂所在芯片编号
        /// </summary>
        public string CanID
        {
            get { return mCanID; }
            set { mCanID = value; }
        }
        /// <summary>
        /// 等待完成
        /// </summary>
        public AutoResetEvent CompleteReset
        {
            get
            {
                return mCompleteReset;
            }
        }
        /// <summary>
        /// 部件的运行控制状态
        /// </summary>
        public ControlStatusEnum Status
        {
            get
            {
                return mStatus;
            }
            set
            {
                mStatus = value;
                if (value==ControlStatusEnum.IDLE)
                {
                    mCompleteReset.Set();
                }
            }
        }
        #endregion // -------属性---------------

        #region // 构造函数
        public Arm(string armName, string canID)
        {
            mArmName = armName;
            mCanID = canID;
            mMotors = new Motor[4];
            mMotors[0] = new Motor("0");
            mMotors[1] = new Motor("1");
            mMotors[2] = new Motor("2");
            mMotors[3] = new Motor("3");            
        }
        #endregion // 构造函数

        #region // 臂抬起或放下
        public string PutUpOrDown(byte motorID, int position,bool isUp)
        {
            string cmd = "";

            if (isUp)
            {
                cmd = mMotors[motorID].FeedLength(position);
            }
            else
            {
                cmd = mMotors[motorID].FeedLength(-position);
            }
            return cmd;
        }
        #endregion // 臂抬起或放下

        #region // 臂向左或向右旋转
        public string RotateToLeftOrRight(bool isClockWise, int motorID,int coderNo, byte sensorNo, string levelStatus)
        {
            string cmd = mMotors[motorID].Feed_Encord(isClockWise, coderNo, sensorNo, levelStatus);
            return cmd;
        }
        #endregion // 臂向左或向旋转       

        #region // 传送反应条到指定位置 MV
        public string MoveStripToLength(string canID, byte motorID, int position)
        {
            string cmd = "";
            cmd = mMotors[motorID].FeedLength(position);
            Can.SendDataToCan(Convert.ToInt16(canID), cmd);
            return cmd;
        }
        #endregion // 传送反应条到指定位置

        #region // 传送反应条到定位传感器1 SE（用于两试剂盘和孵育床的震荡电机）
        // position是指用于判断是否转指定传感器的距离
        public string MoveStripToSensorSE(string canID, byte motorID, bool isClockWise, byte sensorNo, string levelStatus, int dclength)
        {
            string cmd = "";
            cmd = mMotors[motorID].Seek_Encord(isClockWise, sensorNo, levelStatus, dclength);
            Can.SendDataToCan(Convert.ToInt16(canID), cmd);
            return cmd;
        }
        #endregion // 传送反应条到指定传感器

        #region // 传送反应条到定位传感器2 FE
        // position是指判断传感器所在位置的距离
        public string MoveStripToSensorFE(string canID, byte motorID, bool isClockWise, byte sensorNo, string levelStatus, int ed_num)
        {
            string cmd = "";
            cmd = mMotors[motorID].Feed_Encord(isClockWise,ed_num, sensorNo, levelStatus);
            Can.SendDataToCan(Convert.ToInt16(canID), cmd);
            return cmd;
        }
        #endregion // 传送反应条到指定传感器

        #region // 传送反应条到限位传感器1 SH        
        public string MoveStripToSensorSH(string canID, byte motorID, bool isClockWise, byte sensorNo, string levelStatus)
        {
            string cmd = "";
            cmd = mMotors[motorID].SeekHome(isClockWise, sensorNo, levelStatus);
            Can.SendDataToCan(Convert.ToInt16(canID), cmd);
            return cmd;
        }
        #endregion // 传送反应条到指定传感器

        #region // ----------臂的组合动作--------------

        #region // 定位试剂盘 LR
        public string LocateReagentDish(byte reagentNum)
        {
            string cmd = "";
            //// 试剂盘回零（SE的最一个参数值是多少？第一个参数是True，还是False？）
            //cmd = mMotors[3].Seek_Encord(true, 4, "R", 2000);

            //// 试剂盘旋转到指定位置（reagentNum为试剂位置编号）
            //cmd += mMotors[3].Feed_Encord(true, reagentNum, 4, "R"); 

            cmd = mCanID + ",LR,"+ reagentNum.ToString();
            return cmd;
        }
        #endregion // 定位试剂盘

        #region // 定位样本架 LS
        public string LocateSampleShelf(string shelfBarcode, byte siteNum)
        {
            string cmd = "";
            cmd = mCanID + ",LS," + shelfBarcode + "," + siteNum.ToString();
            return cmd;
        }
        #endregion // 定位样本架

        #region  // 吸液 AP
        public string Aspirate(int volume)
        {
            string cmd = "";

            //// 臂旋转到吸液位(?使用距离，还是传感器)
            //cmd += mMotors[1].FeedLength(position);

            //// 臂下降到一定高度（？与页面探测结合使用）
            //cmd += mMotors[0].FeedLength(800);

            //// 臂吸液（？吸液量与步数的换算关系）
            //cmd += mMotors[2].FeedLength(800);

            //// 臂抬起
            //cmd += mMotors[0].SeekHome(true, 1, "R");

            cmd = mCanID + ",AP," + volume.ToString(); 
            return cmd;
        }
        #endregion  // 吸液

        #region  // 加液 DP
        public string Dispense()
        {
            string cmd = "";

            //// 臂旋转到加液位(?使用距离，还是传感器)
            //cmd += mMotors[1].FeedLength(12);

            //// 臂下降到一定高度（？与页面探测结合使用）
            //cmd += mMotors[0].FeedLength(800);

            //// 加液（？吸液量与步数的换算关系）
            //cmd += mMotors[2].FeedLength(-800);

            //// 臂抬起
            //cmd += mMotors[0].SeekHome(true, 1, "R");

            cmd = mCanID + ",DP";
            return cmd;
        }
        #endregion  // 加液

        #region  // 洗针 RN
        public string RinseNeedle()
        {
            string cmd = "";

            //// 臂旋转到洗针位(?使用距离，还是传感器)
            //cmd += mMotors[1].Feed_Encord(false, 3, 2, "R");

            //// 臂下降到一定高度（？）
            //cmd += mMotors[0].FeedLength(800);

            //for (int i = 0; i < washTimes; i++)
            //{
            //    // 清洗内壁（？）

            //    // 清洗外壁（？）
            //}
            //// 臂抬起
            //cmd += mMotors[0].SeekHome(true, 1, "R");

            cmd = mCanID + ",RN";
            return cmd;
        }
        #endregion  // 洗针

        #region  // 摇晃或停止摇晃孵育床 RK
        public string Rock( bool isShake)
        {
            string cmd = "";

            if (isShake)
            {
                cmd = mCanID + ",RK,1";    // 开始振荡
            }
            else
            {
                cmd = mCanID + ",RK,0";    // 停止振荡
            }
            return cmd;
        }
        #endregion  // 孵育床开始摇晃或停止摇晃

        //#region // 放反应条 DS
        //public string DropStrip( byte site)
        //{
        //    string cmd = "";
        //    cmd = mCanID + ",DS," + site.ToString(); 
        //    return cmd;
        //}
        //#endregion // 放反应条

        //#region // 取反应条 GS
        //public string GetStrip(byte site)
        //{
        //    string cmd = "";
        //    cmd = mCanID + ",GS," + site.ToString();             
        //    return cmd;
        //}
        //#endregion // 取反应条

        #region  // 洗板 WS
        public string WashStrip(byte site)
        {
            string cmd = "";
            cmd = mCanID + ",WS," + site.ToString();
            return cmd;
        }
        #endregion  // 洗板

        #region  // 加底物 AS
        public string AddSubstrate()
        {
            string cmd = "";
            cmd = mCanID + ",AS";
            return cmd;
        }
        #endregion  // 加底物

        #region  // 检测 DT
        public string Detect()
        {
            string cmd = "";
            cmd = mCanID + ",DT";
            return cmd;
        }
        #endregion  // 检测

        #region  // 扫条码 SC
        public string ScanBarcod(byte scannerID)
        {
            string cmd = scannerID.ToString() + ",SC";
            return cmd;
        }
        #endregion  // 扫条码

        #region // 针回零 NH
        public string NeedleHoming()
        {
            string cmd = mCanID + ",NH";
            return cmd;
        }
        #endregion // 针回零 NH

        #endregion // ----------臂的组合动作--------------
    }
}
